home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2007 September / PCWSEP07.iso / Software / Linux / Linux Mint 3.0 Light / LinuxMint-3.0-Light.iso / casper / filesystem.squashfs / usr / lib / python2.5 / tarfile.pyc (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2007-05-11  |  59.1 KB  |  2,215 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.5)
  3.  
  4. '''Read from and write to tar format archives.
  5. '''
  6. __version__ = '$Revision: 53162 $'
  7. version = '0.8.0'
  8. __author__ = 'Lars Gust\xe4bel (lars@gustaebel.de)'
  9. __date__ = '$Date: 2006-12-27 21:36:58 +1100 (Wed, 27 Dec 2006) $'
  10. __cvsid__ = '$Id: tarfile.py 53162 2006-12-27 10:36:58Z lars.gustaebel $'
  11. __credits__ = 'Gustavo Niemeyer, Niels Gust\xe4bel, Richard Townsend.'
  12. import sys
  13. import os
  14. import shutil
  15. import stat
  16. import errno
  17. import time
  18. import struct
  19. import copy
  20. if sys.platform == 'mac':
  21.     raise ImportError, 'tarfile does not work for platform==mac'
  22.  
  23.  
  24. try:
  25.     import grp
  26.     import pwd
  27. except ImportError:
  28.     grp = pwd = None
  29.  
  30. __all__ = [
  31.     'TarFile',
  32.     'TarInfo',
  33.     'is_tarfile',
  34.     'TarError']
  35. NUL = '\x00'
  36. BLOCKSIZE = 512
  37. RECORDSIZE = BLOCKSIZE * 20
  38. MAGIC = 'ustar'
  39. VERSION = '00'
  40. LENGTH_NAME = 100
  41. LENGTH_LINK = 100
  42. LENGTH_PREFIX = 155
  43. MAXSIZE_MEMBER = 0x1FFFFFFFFL
  44. REGTYPE = '0'
  45. AREGTYPE = '\x00'
  46. LNKTYPE = '1'
  47. SYMTYPE = '2'
  48. CHRTYPE = '3'
  49. BLKTYPE = '4'
  50. DIRTYPE = '5'
  51. FIFOTYPE = '6'
  52. CONTTYPE = '7'
  53. GNUTYPE_LONGNAME = 'L'
  54. GNUTYPE_LONGLINK = 'K'
  55. GNUTYPE_SPARSE = 'S'
  56. SUPPORTED_TYPES = (REGTYPE, AREGTYPE, LNKTYPE, SYMTYPE, DIRTYPE, FIFOTYPE, CONTTYPE, CHRTYPE, BLKTYPE, GNUTYPE_LONGNAME, GNUTYPE_LONGLINK, GNUTYPE_SPARSE)
  57. REGULAR_TYPES = (REGTYPE, AREGTYPE, CONTTYPE, GNUTYPE_SPARSE)
  58. S_IFLNK = 40960
  59. S_IFREG = 32768
  60. S_IFBLK = 24576
  61. S_IFDIR = 16384
  62. S_IFCHR = 8192
  63. S_IFIFO = 4096
  64. TSUID = 2048
  65. TSGID = 1024
  66. TSVTX = 512
  67. TUREAD = 256
  68. TUWRITE = 128
  69. TUEXEC = 64
  70. TGREAD = 32
  71. TGWRITE = 16
  72. TGEXEC = 8
  73. TOREAD = 4
  74. TOWRITE = 2
  75. TOEXEC = 1
  76.  
  77. def stn(s, length):
  78.     '''Convert a python string to a null-terminated string buffer.
  79.     '''
  80.     return s[:length] + (length - len(s)) * NUL
  81.  
  82.  
  83. def nti(s):
  84.     '''Convert a number field to a python number.
  85.     '''
  86.     if s[0] != chr(128):
  87.         if not s.rstrip(NUL + ' '):
  88.             pass
  89.         n = int('0', 8)
  90.     else:
  91.         n = 0x0L
  92.         for i in xrange(len(s) - 1):
  93.             n <<= 8
  94.             n += ord(s[i + 1])
  95.         
  96.     return n
  97.  
  98.  
  99. def itn(n, digits = 8, posix = False):
  100.     '''Convert a python number to a number field.
  101.     '''
  102.     if n <= n:
  103.         pass
  104.     elif n < 8 ** (digits - 1):
  105.         s = '%0*o' % (digits - 1, n) + NUL
  106.     elif posix:
  107.         raise ValueError('overflow in number field')
  108.     
  109.     if n < 0:
  110.         n = struct.unpack('L', struct.pack('l', n))[0]
  111.     
  112.     s = ''
  113.     for i in xrange(digits - 1):
  114.         s = chr(n & 255) + s
  115.         n >>= 8
  116.     
  117.     s = chr(128) + s
  118.     return s
  119.  
  120.  
  121. def calc_chksums(buf):
  122.     """Calculate the checksum for a member's header by summing up all
  123.        characters except for the chksum field which is treated as if
  124.        it was filled with spaces. According to the GNU tar sources,
  125.        some tars (Sun and NeXT) calculate chksum with signed char,
  126.        which will be different if there are chars in the buffer with
  127.        the high bit set. So we calculate two checksums, unsigned and
  128.        signed.
  129.     """
  130.     unsigned_chksum = 256 + sum(struct.unpack('148B', buf[:148]) + struct.unpack('356B', buf[156:512]))
  131.     signed_chksum = 256 + sum(struct.unpack('148b', buf[:148]) + struct.unpack('356b', buf[156:512]))
  132.     return (unsigned_chksum, signed_chksum)
  133.  
  134.  
  135. def copyfileobj(src, dst, length = None):
  136.     '''Copy length bytes from fileobj src to fileobj dst.
  137.        If length is None, copy the entire content.
  138.     '''
  139.     if length == 0:
  140.         return None
  141.     
  142.     if length is None:
  143.         shutil.copyfileobj(src, dst)
  144.         return None
  145.     
  146.     BUFSIZE = 16384
  147.     (blocks, remainder) = divmod(length, BUFSIZE)
  148.     for b in xrange(blocks):
  149.         buf = src.read(BUFSIZE)
  150.         if len(buf) < BUFSIZE:
  151.             raise IOError('end of file reached')
  152.         
  153.         dst.write(buf)
  154.     
  155.     if remainder != 0:
  156.         buf = src.read(remainder)
  157.         if len(buf) < remainder:
  158.             raise IOError('end of file reached')
  159.         
  160.         dst.write(buf)
  161.     
  162.  
  163. filemode_table = (((S_IFLNK, 'l'), (S_IFREG, '-'), (S_IFBLK, 'b'), (S_IFDIR, 'd'), (S_IFCHR, 'c'), (S_IFIFO, 'p')), ((TUREAD, 'r'),), ((TUWRITE, 'w'),), ((TUEXEC | TSUID, 's'), (TSUID, 'S'), (TUEXEC, 'x')), ((TGREAD, 'r'),), ((TGWRITE, 'w'),), ((TGEXEC | TSGID, 's'), (TSGID, 'S'), (TGEXEC, 'x')), ((TOREAD, 'r'),), ((TOWRITE, 'w'),), ((TOEXEC | TSVTX, 't'), (TSVTX, 'T'), (TOEXEC, 'x')))
  164.  
  165. def filemode(mode):
  166.     """Convert a file's mode to a string of the form
  167.        -rwxrwxrwx.
  168.        Used by TarFile.list()
  169.     """
  170.     perm = []
  171.     for table in filemode_table:
  172.         for bit, char in table:
  173.             if mode & bit == bit:
  174.                 perm.append(char)
  175.                 break
  176.                 continue
  177.         
  178.     
  179.     return ''.join(perm)
  180.  
  181. if os.sep != '/':
  182.     
  183.     normpath = lambda path: os.path.normpath(path).replace(os.sep, '/')
  184. else:
  185.     normpath = os.path.normpath
  186.  
  187. class TarError(Exception):
  188.     '''Base exception.'''
  189.     pass
  190.  
  191.  
  192. class ExtractError(TarError):
  193.     '''General exception for extract errors.'''
  194.     pass
  195.  
  196.  
  197. class ReadError(TarError):
  198.     '''Exception for unreadble tar archives.'''
  199.     pass
  200.  
  201.  
  202. class CompressionError(TarError):
  203.     '''Exception for unavailable compression methods.'''
  204.     pass
  205.  
  206.  
  207. class StreamError(TarError):
  208.     '''Exception for unsupported operations on stream-like TarFiles.'''
  209.     pass
  210.  
  211.  
  212. class _LowLevelFile:
  213.     '''Low-level file object. Supports reading and writing.
  214.        It is used instead of a regular file object for streaming
  215.        access.
  216.     '''
  217.     
  218.     def __init__(self, name, mode):
  219.         mode = {
  220.             'r': os.O_RDONLY,
  221.             'w': os.O_WRONLY | os.O_CREAT | os.O_TRUNC }[mode]
  222.         if hasattr(os, 'O_BINARY'):
  223.             mode |= os.O_BINARY
  224.         
  225.         self.fd = os.open(name, mode)
  226.  
  227.     
  228.     def close(self):
  229.         os.close(self.fd)
  230.  
  231.     
  232.     def read(self, size):
  233.         return os.read(self.fd, size)
  234.  
  235.     
  236.     def write(self, s):
  237.         os.write(self.fd, s)
  238.  
  239.  
  240.  
  241. class _Stream:
  242.     '''Class that serves as an adapter between TarFile and
  243.        a stream-like object.  The stream-like object only
  244.        needs to have a read() or write() method and is accessed
  245.        blockwise.  Use of gzip or bzip2 compression is possible.
  246.        A stream-like object could be for example: sys.stdin,
  247.        sys.stdout, a socket, a tape device etc.
  248.  
  249.        _Stream is intended to be used only internally.
  250.     '''
  251.     
  252.     def __init__(self, name, mode, comptype, fileobj, bufsize):
  253.         '''Construct a _Stream object.
  254.         '''
  255.         self._extfileobj = True
  256.         if fileobj is None:
  257.             fileobj = _LowLevelFile(name, mode)
  258.             self._extfileobj = False
  259.         
  260.         if comptype == '*':
  261.             fileobj = _StreamProxy(fileobj)
  262.             comptype = fileobj.getcomptype()
  263.         
  264.         if not name:
  265.             pass
  266.         self.name = ''
  267.         self.mode = mode
  268.         self.comptype = comptype
  269.         self.fileobj = fileobj
  270.         self.bufsize = bufsize
  271.         self.buf = ''
  272.         self.pos = 0x0L
  273.         self.closed = False
  274.         if comptype == 'gz':
  275.             
  276.             try:
  277.                 import zlib
  278.             except ImportError:
  279.                 raise CompressionError('zlib module is not available')
  280.  
  281.             self.zlib = zlib
  282.             self.crc = zlib.crc32('')
  283.             if mode == 'r':
  284.                 self._init_read_gz()
  285.             else:
  286.                 self._init_write_gz()
  287.         
  288.         if comptype == 'bz2':
  289.             
  290.             try:
  291.                 import bz2
  292.             except ImportError:
  293.                 raise CompressionError('bz2 module is not available')
  294.  
  295.             if mode == 'r':
  296.                 self.dbuf = ''
  297.                 self.cmp = bz2.BZ2Decompressor()
  298.             else:
  299.                 self.cmp = bz2.BZ2Compressor()
  300.         
  301.  
  302.     
  303.     def __del__(self):
  304.         if hasattr(self, 'closed') and not (self.closed):
  305.             self.close()
  306.         
  307.  
  308.     
  309.     def _init_write_gz(self):
  310.         '''Initialize for writing with gzip compression.
  311.         '''
  312.         self.cmp = self.zlib.compressobj(9, self.zlib.DEFLATED, -(self.zlib.MAX_WBITS), self.zlib.DEF_MEM_LEVEL, 0)
  313.         timestamp = struct.pack('<L', long(time.time()))
  314.         self._Stream__write('\x1f\x8b\x08\x08%s\x02\xff' % timestamp)
  315.         if self.name.endswith('.gz'):
  316.             self.name = self.name[:-3]
  317.         
  318.         self._Stream__write(self.name + NUL)
  319.  
  320.     
  321.     def write(self, s):
  322.         '''Write string s to the stream.
  323.         '''
  324.         if self.comptype == 'gz':
  325.             self.crc = self.zlib.crc32(s, self.crc)
  326.         
  327.         self.pos += len(s)
  328.         if self.comptype != 'tar':
  329.             s = self.cmp.compress(s)
  330.         
  331.         self._Stream__write(s)
  332.  
  333.     
  334.     def _Stream__write(self, s):
  335.         '''Write string s to the stream if a whole new block
  336.            is ready to be written.
  337.         '''
  338.         self.buf += s
  339.         while len(self.buf) > self.bufsize:
  340.             self.fileobj.write(self.buf[:self.bufsize])
  341.             self.buf = self.buf[self.bufsize:]
  342.             continue
  343.             self
  344.  
  345.     
  346.     def close(self):
  347.         '''Close the _Stream object. No operation should be
  348.            done on it afterwards.
  349.         '''
  350.         if self.closed:
  351.             return None
  352.         
  353.         if self.mode == 'w' and self.comptype != 'tar':
  354.             self.buf += self.cmp.flush()
  355.         
  356.         if self.mode == 'w' and self.buf:
  357.             self.fileobj.write(self.buf)
  358.             self.buf = ''
  359.             if self.comptype == 'gz':
  360.                 self.fileobj.write(struct.pack('<L', self.crc & 0xFFFFFFFFL))
  361.                 self.fileobj.write(struct.pack('<L', self.pos & 0xFFFFFFFFL))
  362.             
  363.         
  364.         if not self._extfileobj:
  365.             self.fileobj.close()
  366.         
  367.         self.closed = True
  368.  
  369.     
  370.     def _init_read_gz(self):
  371.         '''Initialize for reading a gzip compressed fileobj.
  372.         '''
  373.         self.cmp = self.zlib.decompressobj(-(self.zlib.MAX_WBITS))
  374.         self.dbuf = ''
  375.         if self._Stream__read(2) != '\x1f\x8b':
  376.             raise ReadError('not a gzip file')
  377.         
  378.         if self._Stream__read(1) != '\x08':
  379.             raise CompressionError('unsupported compression method')
  380.         
  381.         flag = ord(self._Stream__read(1))
  382.         self._Stream__read(6)
  383.         if flag & 4:
  384.             xlen = ord(self._Stream__read(1)) + 256 * ord(self._Stream__read(1))
  385.             self.read(xlen)
  386.         
  387.         if flag & 8:
  388.             while True:
  389.                 s = self._Stream__read(1)
  390.                 if not s or s == NUL:
  391.                     break
  392.                     continue
  393.         
  394.         if flag & 16:
  395.             while True:
  396.                 s = self._Stream__read(1)
  397.                 if not s or s == NUL:
  398.                     break
  399.                     continue
  400.         
  401.         if flag & 2:
  402.             self._Stream__read(2)
  403.         
  404.  
  405.     
  406.     def tell(self):
  407.         """Return the stream's file pointer position.
  408.         """
  409.         return self.pos
  410.  
  411.     
  412.     def seek(self, pos = 0):
  413.         """Set the stream's file pointer to pos. Negative seeking
  414.            is forbidden.
  415.         """
  416.         if pos - self.pos >= 0:
  417.             (blocks, remainder) = divmod(pos - self.pos, self.bufsize)
  418.             for i in xrange(blocks):
  419.                 self.read(self.bufsize)
  420.             
  421.             self.read(remainder)
  422.         else:
  423.             raise StreamError('seeking backwards is not allowed')
  424.         return self.pos
  425.  
  426.     
  427.     def read(self, size = None):
  428.         '''Return the next size number of bytes from the stream.
  429.            If size is not defined, return all bytes of the stream
  430.            up to EOF.
  431.         '''
  432.         if size is None:
  433.             t = []
  434.             while True:
  435.                 buf = self._read(self.bufsize)
  436.                 if not buf:
  437.                     break
  438.                 
  439.                 t.append(buf)
  440.             buf = ''.join(t)
  441.         else:
  442.             buf = self._read(size)
  443.         self.pos += len(buf)
  444.         return buf
  445.  
  446.     
  447.     def _read(self, size):
  448.         '''Return size bytes from the stream.
  449.         '''
  450.         if self.comptype == 'tar':
  451.             return self._Stream__read(size)
  452.         
  453.         c = len(self.dbuf)
  454.         t = [
  455.             self.dbuf]
  456.         while c < size:
  457.             buf = self._Stream__read(self.bufsize)
  458.             if not buf:
  459.                 break
  460.             
  461.             buf = self.cmp.decompress(buf)
  462.             t.append(buf)
  463.             c += len(buf)
  464.         t = ''.join(t)
  465.         self.dbuf = t[size:]
  466.         return t[:size]
  467.  
  468.     
  469.     def _Stream__read(self, size):
  470.         '''Return size bytes from stream. If internal buffer is empty,
  471.            read another block from the stream.
  472.         '''
  473.         c = len(self.buf)
  474.         t = [
  475.             self.buf]
  476.         while c < size:
  477.             buf = self.fileobj.read(self.bufsize)
  478.             if not buf:
  479.                 break
  480.             
  481.             t.append(buf)
  482.             c += len(buf)
  483.         t = ''.join(t)
  484.         self.buf = t[size:]
  485.         return t[:size]
  486.  
  487.  
  488.  
  489. class _StreamProxy(object):
  490.     """Small proxy class that enables transparent compression
  491.        detection for the Stream interface (mode 'r|*').
  492.     """
  493.     
  494.     def __init__(self, fileobj):
  495.         self.fileobj = fileobj
  496.         self.buf = self.fileobj.read(BLOCKSIZE)
  497.  
  498.     
  499.     def read(self, size):
  500.         self.read = self.fileobj.read
  501.         return self.buf
  502.  
  503.     
  504.     def getcomptype(self):
  505.         if self.buf.startswith('\x1f\x8b\x08'):
  506.             return 'gz'
  507.         
  508.         if self.buf.startswith('BZh91'):
  509.             return 'bz2'
  510.         
  511.         return 'tar'
  512.  
  513.     
  514.     def close(self):
  515.         self.fileobj.close()
  516.  
  517.  
  518.  
  519. class _BZ2Proxy(object):
  520.     '''Small proxy class that enables external file object
  521.        support for "r:bz2" and "w:bz2" modes. This is actually
  522.        a workaround for a limitation in bz2 module\'s BZ2File
  523.        class which (unlike gzip.GzipFile) has no support for
  524.        a file object argument.
  525.     '''
  526.     blocksize = 16384
  527.     
  528.     def __init__(self, fileobj, mode):
  529.         self.fileobj = fileobj
  530.         self.mode = mode
  531.         self.init()
  532.  
  533.     
  534.     def init(self):
  535.         import bz2
  536.         self.pos = 0
  537.         if self.mode == 'r':
  538.             self.bz2obj = bz2.BZ2Decompressor()
  539.             self.fileobj.seek(0)
  540.             self.buf = ''
  541.         else:
  542.             self.bz2obj = bz2.BZ2Compressor()
  543.  
  544.     
  545.     def read(self, size):
  546.         b = [
  547.             self.buf]
  548.         x = len(self.buf)
  549.         while x < size:
  550.             
  551.             try:
  552.                 raw = self.fileobj.read(self.blocksize)
  553.                 data = self.bz2obj.decompress(raw)
  554.                 b.append(data)
  555.             except EOFError:
  556.                 break
  557.  
  558.             x += len(data)
  559.         self.buf = ''.join(b)
  560.         buf = self.buf[:size]
  561.         self.buf = self.buf[size:]
  562.         self.pos += len(buf)
  563.         return buf
  564.  
  565.     
  566.     def seek(self, pos):
  567.         if pos < self.pos:
  568.             self.init()
  569.         
  570.         self.read(pos - self.pos)
  571.  
  572.     
  573.     def tell(self):
  574.         return self.pos
  575.  
  576.     
  577.     def write(self, data):
  578.         self.pos += len(data)
  579.         raw = self.bz2obj.compress(data)
  580.         self.fileobj.write(raw)
  581.  
  582.     
  583.     def close(self):
  584.         if self.mode == 'w':
  585.             raw = self.bz2obj.flush()
  586.             self.fileobj.write(raw)
  587.         
  588.         self.fileobj.close()
  589.  
  590.  
  591.  
  592. class _FileInFile(object):
  593.     '''A thin wrapper around an existing file object that
  594.        provides a part of its data as an individual file
  595.        object.
  596.     '''
  597.     
  598.     def __init__(self, fileobj, offset, size, sparse = None):
  599.         self.fileobj = fileobj
  600.         self.offset = offset
  601.         self.size = size
  602.         self.sparse = sparse
  603.         self.position = 0
  604.  
  605.     
  606.     def tell(self):
  607.         '''Return the current file position.
  608.         '''
  609.         return self.position
  610.  
  611.     
  612.     def seek(self, position):
  613.         '''Seek to a position in the file.
  614.         '''
  615.         self.position = position
  616.  
  617.     
  618.     def read(self, size = None):
  619.         '''Read data from the file.
  620.         '''
  621.         if size is None:
  622.             size = self.size - self.position
  623.         else:
  624.             size = min(size, self.size - self.position)
  625.         if self.sparse is None:
  626.             return self.readnormal(size)
  627.         else:
  628.             return self.readsparse(size)
  629.  
  630.     
  631.     def readnormal(self, size):
  632.         '''Read operation for regular files.
  633.         '''
  634.         self.fileobj.seek(self.offset + self.position)
  635.         self.position += size
  636.         return self.fileobj.read(size)
  637.  
  638.     
  639.     def readsparse(self, size):
  640.         '''Read operation for sparse files.
  641.         '''
  642.         data = []
  643.         while size > 0:
  644.             buf = self.readsparsesection(size)
  645.             if not buf:
  646.                 break
  647.             
  648.             size -= len(buf)
  649.             data.append(buf)
  650.         return ''.join(data)
  651.  
  652.     
  653.     def readsparsesection(self, size):
  654.         '''Read a single section of a sparse file.
  655.         '''
  656.         section = self.sparse.find(self.position)
  657.         if section is None:
  658.             return ''
  659.         
  660.         size = min(size, section.offset + section.size - self.position)
  661.  
  662.  
  663.  
  664. class ExFileObject(object):
  665.     '''File-like object for reading an archive member.
  666.        Is returned by TarFile.extractfile().
  667.     '''
  668.     blocksize = 1024
  669.     
  670.     def __init__(self, tarfile, tarinfo):
  671.         self.fileobj = _FileInFile(tarfile.fileobj, tarinfo.offset_data, tarinfo.size, getattr(tarinfo, 'sparse', None))
  672.         self.name = tarinfo.name
  673.         self.mode = 'r'
  674.         self.closed = False
  675.         self.size = tarinfo.size
  676.         self.position = 0
  677.         self.buffer = ''
  678.  
  679.     
  680.     def read(self, size = None):
  681.         '''Read at most size bytes from the file. If size is not
  682.            present or None, read all data until EOF is reached.
  683.         '''
  684.         if self.closed:
  685.             raise ValueError('I/O operation on closed file')
  686.         
  687.         buf = ''
  688.         if self.buffer:
  689.             if size is None:
  690.                 buf = self.buffer
  691.                 self.buffer = ''
  692.             else:
  693.                 buf = self.buffer[:size]
  694.                 self.buffer = self.buffer[size:]
  695.         
  696.         if size is None:
  697.             buf += self.fileobj.read()
  698.         else:
  699.             buf += self.fileobj.read(size - len(buf))
  700.         self.position += len(buf)
  701.         return buf
  702.  
  703.     
  704.     def readline(self, size = -1):
  705.         '''Read one entire line from the file. If size is present
  706.            and non-negative, return a string with at most that
  707.            size, which may be an incomplete line.
  708.         '''
  709.         if self.closed:
  710.             raise ValueError('I/O operation on closed file')
  711.         
  712.         if '\n' in self.buffer:
  713.             pos = self.buffer.find('\n') + 1
  714.         else:
  715.             buffers = [
  716.                 self.buffer]
  717.             while True:
  718.                 buf = self.fileobj.read(self.blocksize)
  719.                 buffers.append(buf)
  720.                 if not buf or '\n' in buf:
  721.                     self.buffer = ''.join(buffers)
  722.                     pos = self.buffer.find('\n') + 1
  723.                     if pos == 0:
  724.                         pos = len(self.buffer)
  725.                     
  726.                     break
  727.                     continue
  728.         if size != -1:
  729.             pos = min(size, pos)
  730.         
  731.         buf = self.buffer[:pos]
  732.         self.buffer = self.buffer[pos:]
  733.         self.position += len(buf)
  734.         return buf
  735.  
  736.     
  737.     def readlines(self):
  738.         '''Return a list with all remaining lines.
  739.         '''
  740.         result = []
  741.         while True:
  742.             line = self.readline()
  743.             if not line:
  744.                 break
  745.             
  746.             result.append(line)
  747.         return result
  748.  
  749.     
  750.     def tell(self):
  751.         '''Return the current file position.
  752.         '''
  753.         if self.closed:
  754.             raise ValueError('I/O operation on closed file')
  755.         
  756.         return self.position
  757.  
  758.     
  759.     def seek(self, pos, whence = os.SEEK_SET):
  760.         '''Seek to a position in the file.
  761.         '''
  762.         if self.closed:
  763.             raise ValueError('I/O operation on closed file')
  764.         
  765.         if whence == os.SEEK_SET:
  766.             self.position = min(max(pos, 0), self.size)
  767.         elif whence == os.SEEK_CUR:
  768.             if pos < 0:
  769.                 self.position = max(self.position + pos, 0)
  770.             else:
  771.                 self.position = min(self.position + pos, self.size)
  772.         elif whence == os.SEEK_END:
  773.             self.position = max(min(self.size + pos, self.size), 0)
  774.         else:
  775.             raise ValueError('Invalid argument')
  776.         self.buffer = ''
  777.         self.fileobj.seek(self.position)
  778.  
  779.     
  780.     def close(self):
  781.         '''Close the file object.
  782.         '''
  783.         self.closed = True
  784.  
  785.     
  786.     def __iter__(self):
  787.         """Get an iterator over the file's lines.
  788.         """
  789.         while True:
  790.             line = self.readline()
  791.             if not line:
  792.                 break
  793.             
  794.             yield line
  795.  
  796.  
  797.  
  798. class TarInfo(object):
  799.     '''Informational class which holds the details about an
  800.        archive member given by a tar header block.
  801.        TarInfo objects are returned by TarFile.getmember(),
  802.        TarFile.getmembers() and TarFile.gettarinfo() and are
  803.        usually created internally.
  804.     '''
  805.     
  806.     def __init__(self, name = ''):
  807.         '''Construct a TarInfo object. name is the optional name
  808.            of the member.
  809.         '''
  810.         self.name = name
  811.         self.mode = 438
  812.         self.uid = 0
  813.         self.gid = 0
  814.         self.size = 0
  815.         self.mtime = 0
  816.         self.chksum = 0
  817.         self.type = REGTYPE
  818.         self.linkname = ''
  819.         self.uname = 'user'
  820.         self.gname = 'group'
  821.         self.devmajor = 0
  822.         self.devminor = 0
  823.         self.offset = 0
  824.         self.offset_data = 0
  825.  
  826.     
  827.     def __repr__(self):
  828.         return '<%s %r at %#x>' % (self.__class__.__name__, self.name, id(self))
  829.  
  830.     
  831.     def frombuf(cls, buf):
  832.         '''Construct a TarInfo object from a 512 byte string buffer.
  833.         '''
  834.         if len(buf) != BLOCKSIZE:
  835.             raise ValueError('truncated header')
  836.         
  837.         if buf.count(NUL) == BLOCKSIZE:
  838.             raise ValueError('empty header')
  839.         
  840.         tarinfo = cls()
  841.         tarinfo.buf = buf
  842.         tarinfo.name = buf[0:100].rstrip(NUL)
  843.         tarinfo.mode = nti(buf[100:108])
  844.         tarinfo.uid = nti(buf[108:116])
  845.         tarinfo.gid = nti(buf[116:124])
  846.         tarinfo.size = nti(buf[124:136])
  847.         tarinfo.mtime = nti(buf[136:148])
  848.         tarinfo.chksum = nti(buf[148:156])
  849.         tarinfo.type = buf[156:157]
  850.         tarinfo.linkname = buf[157:257].rstrip(NUL)
  851.         tarinfo.uname = buf[265:297].rstrip(NUL)
  852.         tarinfo.gname = buf[297:329].rstrip(NUL)
  853.         tarinfo.devmajor = nti(buf[329:337])
  854.         tarinfo.devminor = nti(buf[337:345])
  855.         prefix = buf[345:500].rstrip(NUL)
  856.         if prefix and not tarinfo.issparse():
  857.             tarinfo.name = prefix + '/' + tarinfo.name
  858.         
  859.         if tarinfo.chksum not in calc_chksums(buf):
  860.             raise ValueError('invalid header')
  861.         
  862.         return tarinfo
  863.  
  864.     frombuf = classmethod(frombuf)
  865.     
  866.     def tobuf(self, posix = False):
  867.         '''Return a tar header as a string of 512 byte blocks.
  868.         '''
  869.         buf = ''
  870.         type = self.type
  871.         prefix = ''
  872.         if self.name.endswith('/'):
  873.             type = DIRTYPE
  874.         
  875.         if type in (GNUTYPE_LONGNAME, GNUTYPE_LONGLINK):
  876.             name = self.name
  877.         else:
  878.             name = normpath(self.name)
  879.         if type == DIRTYPE:
  880.             name += '/'
  881.         
  882.         linkname = self.linkname
  883.         if linkname:
  884.             linkname = normpath(linkname)
  885.         
  886.         if posix:
  887.             if self.size > MAXSIZE_MEMBER:
  888.                 raise ValueError('file is too large (>= 8 GB)')
  889.             
  890.             if len(self.linkname) > LENGTH_LINK:
  891.                 raise ValueError('linkname is too long (>%d)' % LENGTH_LINK)
  892.             
  893.             if len(name) > LENGTH_NAME:
  894.                 prefix = name[:LENGTH_PREFIX + 1]
  895.                 while prefix and prefix[-1] != '/':
  896.                     prefix = prefix[:-1]
  897.                 name = name[len(prefix):]
  898.                 prefix = prefix[:-1]
  899.                 if not prefix or len(name) > LENGTH_NAME:
  900.                     raise ValueError('name is too long')
  901.                 
  902.             
  903.         elif len(self.linkname) > LENGTH_LINK:
  904.             buf += self._create_gnulong(self.linkname, GNUTYPE_LONGLINK)
  905.         
  906.         if len(name) > LENGTH_NAME:
  907.             buf += self._create_gnulong(name, GNUTYPE_LONGNAME)
  908.         
  909.         parts = [
  910.             stn(name, 100),
  911.             itn(self.mode & 4095, 8, posix),
  912.             itn(self.uid, 8, posix),
  913.             itn(self.gid, 8, posix),
  914.             itn(self.size, 12, posix),
  915.             itn(self.mtime, 12, posix),
  916.             '        ',
  917.             type,
  918.             stn(self.linkname, 100),
  919.             stn(MAGIC, 6),
  920.             stn(VERSION, 2),
  921.             stn(self.uname, 32),
  922.             stn(self.gname, 32),
  923.             itn(self.devmajor, 8, posix),
  924.             itn(self.devminor, 8, posix),
  925.             stn(prefix, 155)]
  926.         buf += struct.pack('%ds' % BLOCKSIZE, ''.join(parts))
  927.         chksum = calc_chksums(buf[-BLOCKSIZE:])[0]
  928.         buf = buf[:-364] + '%06o\x00' % chksum + buf[-357:]
  929.         self.buf = buf
  930.         return buf
  931.  
  932.     
  933.     def _create_gnulong(self, name, type):
  934.         '''Create a GNU longname/longlink header from name.
  935.            It consists of an extended tar header, with the length
  936.            of the longname as size, followed by data blocks,
  937.            which contain the longname as a null terminated string.
  938.         '''
  939.         name += NUL
  940.         tarinfo = self.__class__()
  941.         tarinfo.name = '././@LongLink'
  942.         tarinfo.type = type
  943.         tarinfo.mode = 0
  944.         tarinfo.size = len(name)
  945.         buf = tarinfo.tobuf()
  946.         buf += name
  947.         (blocks, remainder) = divmod(len(name), BLOCKSIZE)
  948.         if remainder > 0:
  949.             buf += (BLOCKSIZE - remainder) * NUL
  950.         
  951.         return buf
  952.  
  953.     
  954.     def isreg(self):
  955.         return self.type in REGULAR_TYPES
  956.  
  957.     
  958.     def isfile(self):
  959.         return self.isreg()
  960.  
  961.     
  962.     def isdir(self):
  963.         return self.type == DIRTYPE
  964.  
  965.     
  966.     def issym(self):
  967.         return self.type == SYMTYPE
  968.  
  969.     
  970.     def islnk(self):
  971.         return self.type == LNKTYPE
  972.  
  973.     
  974.     def ischr(self):
  975.         return self.type == CHRTYPE
  976.  
  977.     
  978.     def isblk(self):
  979.         return self.type == BLKTYPE
  980.  
  981.     
  982.     def isfifo(self):
  983.         return self.type == FIFOTYPE
  984.  
  985.     
  986.     def issparse(self):
  987.         return self.type == GNUTYPE_SPARSE
  988.  
  989.     
  990.     def isdev(self):
  991.         return self.type in (CHRTYPE, BLKTYPE, FIFOTYPE)
  992.  
  993.  
  994.  
  995. class TarFile(object):
  996.     '''The TarFile Class provides an interface to tar archives.
  997.     '''
  998.     debug = 0
  999.     dereference = False
  1000.     ignore_zeros = False
  1001.     errorlevel = 0
  1002.     posix = False
  1003.     fileobject = ExFileObject
  1004.     
  1005.     def __init__(self, name = None, mode = 'r', fileobj = None):
  1006.         """Open an (uncompressed) tar archive `name'. `mode' is either 'r' to
  1007.            read from an existing archive, 'a' to append data to an existing
  1008.            file or 'w' to create a new file overwriting an existing one. `mode'
  1009.            defaults to 'r'.
  1010.            If `fileobj' is given, it is used for reading or writing data. If it
  1011.            can be determined, `mode' is overridden by `fileobj's mode.
  1012.            `fileobj' is not closed, when TarFile is closed.
  1013.         """
  1014.         self.name = os.path.abspath(name)
  1015.         if len(mode) > 1 or mode not in 'raw':
  1016.             raise ValueError("mode must be 'r', 'a' or 'w'")
  1017.         
  1018.         self._mode = mode
  1019.         self.mode = {
  1020.             'r': 'rb',
  1021.             'a': 'r+b',
  1022.             'w': 'wb' }[mode]
  1023.         if not fileobj:
  1024.             fileobj = file(self.name, self.mode)
  1025.             self._extfileobj = False
  1026.         elif self.name is None and hasattr(fileobj, 'name'):
  1027.             self.name = os.path.abspath(fileobj.name)
  1028.         
  1029.         if hasattr(fileobj, 'mode'):
  1030.             self.mode = fileobj.mode
  1031.         
  1032.         self._extfileobj = True
  1033.         self.fileobj = fileobj
  1034.         self.closed = False
  1035.         self.members = []
  1036.         self._loaded = False
  1037.         self.offset = 0x0L
  1038.         self.inodes = { }
  1039.         if self._mode == 'r':
  1040.             self.firstmember = None
  1041.             self.firstmember = self.next()
  1042.         
  1043.         if self._mode == 'a':
  1044.             self.firstmember = None
  1045.             while True:
  1046.                 
  1047.                 try:
  1048.                     tarinfo = self.next()
  1049.                 except ReadError:
  1050.                     self.fileobj.seek(0)
  1051.                     break
  1052.  
  1053.                 if tarinfo is None:
  1054.                     self.fileobj.seek(-BLOCKSIZE, 1)
  1055.                     break
  1056.                     continue
  1057.         
  1058.         if self._mode in 'aw':
  1059.             self._loaded = True
  1060.         
  1061.  
  1062.     
  1063.     def open(cls, name = None, mode = 'r', fileobj = None, bufsize = 10240):
  1064.         """Open a tar archive for reading, writing or appending. Return
  1065.            an appropriate TarFile class.
  1066.  
  1067.            mode:
  1068.            'r' or 'r:*' open for reading with transparent compression
  1069.            'r:'         open for reading exclusively uncompressed
  1070.            'r:gz'       open for reading with gzip compression
  1071.            'r:bz2'      open for reading with bzip2 compression
  1072.            'a' or 'a:'  open for appending
  1073.            'w' or 'w:'  open for writing without compression
  1074.            'w:gz'       open for writing with gzip compression
  1075.            'w:bz2'      open for writing with bzip2 compression
  1076.  
  1077.            'r|*'        open a stream of tar blocks with transparent compression
  1078.            'r|'         open an uncompressed stream of tar blocks for reading
  1079.            'r|gz'       open a gzip compressed stream of tar blocks
  1080.            'r|bz2'      open a bzip2 compressed stream of tar blocks
  1081.            'w|'         open an uncompressed stream for writing
  1082.            'w|gz'       open a gzip compressed stream for writing
  1083.            'w|bz2'      open a bzip2 compressed stream for writing
  1084.         """
  1085.         if not name and not fileobj:
  1086.             raise ValueError('nothing to open')
  1087.         
  1088.         if mode in ('r', 'r:*'):
  1089.             for comptype in cls.OPEN_METH:
  1090.                 func = getattr(cls, cls.OPEN_METH[comptype])
  1091.                 if fileobj is not None:
  1092.                     saved_pos = fileobj.tell()
  1093.                 
  1094.                 
  1095.                 try:
  1096.                     return func(name, 'r', fileobj)
  1097.                 continue
  1098.                 except (ReadError, CompressionError):
  1099.                     if fileobj is not None:
  1100.                         fileobj.seek(saved_pos)
  1101.                         continue
  1102.                     continue
  1103.                     continue
  1104.                 
  1105.  
  1106.             
  1107.             raise ReadError('file could not be opened successfully')
  1108.         elif ':' in mode:
  1109.             (filemode, comptype) = mode.split(':', 1)
  1110.             if not filemode:
  1111.                 pass
  1112.             filemode = 'r'
  1113.             if not comptype:
  1114.                 pass
  1115.             comptype = 'tar'
  1116.             if comptype in cls.OPEN_METH:
  1117.                 func = getattr(cls, cls.OPEN_METH[comptype])
  1118.             else:
  1119.                 raise CompressionError('unknown compression type %r' % comptype)
  1120.             return func(name, filemode, fileobj)
  1121.         elif '|' in mode:
  1122.             (filemode, comptype) = mode.split('|', 1)
  1123.             if not filemode:
  1124.                 pass
  1125.             filemode = 'r'
  1126.             if not comptype:
  1127.                 pass
  1128.             comptype = 'tar'
  1129.             if filemode not in 'rw':
  1130.                 raise ValueError("mode must be 'r' or 'w'")
  1131.             
  1132.             t = cls(name, filemode, _Stream(name, filemode, comptype, fileobj, bufsize))
  1133.             t._extfileobj = False
  1134.             return t
  1135.         elif mode in 'aw':
  1136.             return cls.taropen(name, mode, fileobj)
  1137.         
  1138.         raise ValueError('undiscernible mode')
  1139.  
  1140.     open = classmethod(open)
  1141.     
  1142.     def taropen(cls, name, mode = 'r', fileobj = None):
  1143.         '''Open uncompressed tar archive name for reading or writing.
  1144.         '''
  1145.         if len(mode) > 1 or mode not in 'raw':
  1146.             raise ValueError("mode must be 'r', 'a' or 'w'")
  1147.         
  1148.         return cls(name, mode, fileobj)
  1149.  
  1150.     taropen = classmethod(taropen)
  1151.     
  1152.     def gzopen(cls, name, mode = 'r', fileobj = None, compresslevel = 9):
  1153.         '''Open gzip compressed tar archive name for reading or writing.
  1154.            Appending is not allowed.
  1155.         '''
  1156.         if len(mode) > 1 or mode not in 'rw':
  1157.             raise ValueError("mode must be 'r' or 'w'")
  1158.         
  1159.         
  1160.         try:
  1161.             import gzip
  1162.             gzip.GzipFile
  1163.         except (ImportError, AttributeError):
  1164.             raise CompressionError('gzip module is not available')
  1165.  
  1166.         if fileobj is None:
  1167.             fileobj = file(name, mode + 'b')
  1168.         
  1169.         
  1170.         try:
  1171.             t = cls.taropen(name, mode, gzip.GzipFile(name, mode, compresslevel, fileobj))
  1172.         except IOError:
  1173.             raise ReadError('not a gzip file')
  1174.  
  1175.         t._extfileobj = False
  1176.         return t
  1177.  
  1178.     gzopen = classmethod(gzopen)
  1179.     
  1180.     def bz2open(cls, name, mode = 'r', fileobj = None, compresslevel = 9):
  1181.         '''Open bzip2 compressed tar archive name for reading or writing.
  1182.            Appending is not allowed.
  1183.         '''
  1184.         if len(mode) > 1 or mode not in 'rw':
  1185.             raise ValueError("mode must be 'r' or 'w'.")
  1186.         
  1187.         
  1188.         try:
  1189.             import bz2
  1190.         except ImportError:
  1191.             raise CompressionError('bz2 module is not available')
  1192.  
  1193.         if fileobj is not None:
  1194.             fileobj = _BZ2Proxy(fileobj, mode)
  1195.         else:
  1196.             fileobj = bz2.BZ2File(name, mode, compresslevel = compresslevel)
  1197.         
  1198.         try:
  1199.             t = cls.taropen(name, mode, fileobj)
  1200.         except IOError:
  1201.             raise ReadError('not a bzip2 file')
  1202.  
  1203.         t._extfileobj = False
  1204.         return t
  1205.  
  1206.     bz2open = classmethod(bz2open)
  1207.     OPEN_METH = {
  1208.         'tar': 'taropen',
  1209.         'gz': 'gzopen',
  1210.         'bz2': 'bz2open' }
  1211.     
  1212.     def close(self):
  1213.         '''Close the TarFile. In write-mode, two finishing zero blocks are
  1214.            appended to the archive.
  1215.         '''
  1216.         if self.closed:
  1217.             return None
  1218.         
  1219.         if self._mode in 'aw':
  1220.             self.fileobj.write(NUL * BLOCKSIZE * 2)
  1221.             self.offset += BLOCKSIZE * 2
  1222.             (blocks, remainder) = divmod(self.offset, RECORDSIZE)
  1223.             if remainder > 0:
  1224.                 self.fileobj.write(NUL * (RECORDSIZE - remainder))
  1225.             
  1226.         
  1227.         if not self._extfileobj:
  1228.             self.fileobj.close()
  1229.         
  1230.         self.closed = True
  1231.  
  1232.     
  1233.     def getmember(self, name):
  1234.         """Return a TarInfo object for member `name'. If `name' can not be
  1235.            found in the archive, KeyError is raised. If a member occurs more
  1236.            than once in the archive, its last occurence is assumed to be the
  1237.            most up-to-date version.
  1238.         """
  1239.         tarinfo = self._getmember(name)
  1240.         if tarinfo is None:
  1241.             raise KeyError('filename %r not found' % name)
  1242.         
  1243.         return tarinfo
  1244.  
  1245.     
  1246.     def getmembers(self):
  1247.         '''Return the members of the archive as a list of TarInfo objects. The
  1248.            list has the same order as the members in the archive.
  1249.         '''
  1250.         self._check()
  1251.         if not self._loaded:
  1252.             self._load()
  1253.         
  1254.         return self.members
  1255.  
  1256.     
  1257.     def getnames(self):
  1258.         '''Return the members of the archive as a list of their names. It has
  1259.            the same order as the list returned by getmembers().
  1260.         '''
  1261.         return [ tarinfo.name for tarinfo in self.getmembers() ]
  1262.  
  1263.     
  1264.     def gettarinfo(self, name = None, arcname = None, fileobj = None):
  1265.         """Create a TarInfo object for either the file `name' or the file
  1266.            object `fileobj' (using os.fstat on its file descriptor). You can
  1267.            modify some of the TarInfo's attributes before you add it using
  1268.            addfile(). If given, `arcname' specifies an alternative name for the
  1269.            file in the archive.
  1270.         """
  1271.         self._check('aw')
  1272.         if fileobj is not None:
  1273.             name = fileobj.name
  1274.         
  1275.         if arcname is None:
  1276.             arcname = name
  1277.         
  1278.         arcname = normpath(arcname)
  1279.         (drv, arcname) = os.path.splitdrive(arcname)
  1280.         while arcname[0:1] == '/':
  1281.             arcname = arcname[1:]
  1282.         tarinfo = TarInfo()
  1283.         if fileobj is None:
  1284.             if hasattr(os, 'lstat') and not (self.dereference):
  1285.                 statres = os.lstat(name)
  1286.             else:
  1287.                 statres = os.stat(name)
  1288.         else:
  1289.             statres = os.fstat(fileobj.fileno())
  1290.         linkname = ''
  1291.         stmd = statres.st_mode
  1292.         if stat.S_ISREG(stmd):
  1293.             inode = (statres.st_ino, statres.st_dev)
  1294.             if not (self.dereference) and statres.st_nlink > 1 and inode in self.inodes:
  1295.                 type = LNKTYPE
  1296.                 linkname = self.inodes[inode]
  1297.             else:
  1298.                 type = REGTYPE
  1299.                 if inode[0]:
  1300.                     self.inodes[inode] = arcname
  1301.                 
  1302.         elif stat.S_ISDIR(stmd):
  1303.             type = DIRTYPE
  1304.             if arcname[-1:] != '/':
  1305.                 arcname += '/'
  1306.             
  1307.         elif stat.S_ISFIFO(stmd):
  1308.             type = FIFOTYPE
  1309.         elif stat.S_ISLNK(stmd):
  1310.             type = SYMTYPE
  1311.             linkname = os.readlink(name)
  1312.         elif stat.S_ISCHR(stmd):
  1313.             type = CHRTYPE
  1314.         elif stat.S_ISBLK(stmd):
  1315.             type = BLKTYPE
  1316.         else:
  1317.             return None
  1318.         tarinfo.name = arcname
  1319.         tarinfo.mode = stmd
  1320.         tarinfo.uid = statres.st_uid
  1321.         tarinfo.gid = statres.st_gid
  1322.         if stat.S_ISREG(stmd):
  1323.             tarinfo.size = statres.st_size
  1324.         else:
  1325.             tarinfo.size = 0x0L
  1326.         tarinfo.mtime = statres.st_mtime
  1327.         tarinfo.type = type
  1328.         tarinfo.linkname = linkname
  1329.         if pwd:
  1330.             
  1331.             try:
  1332.                 tarinfo.uname = pwd.getpwuid(tarinfo.uid)[0]
  1333.             except KeyError:
  1334.                 pass
  1335.             except:
  1336.                 None<EXCEPTION MATCH>KeyError
  1337.             
  1338.  
  1339.         None<EXCEPTION MATCH>KeyError
  1340.         if grp:
  1341.             
  1342.             try:
  1343.                 tarinfo.gname = grp.getgrgid(tarinfo.gid)[0]
  1344.             except KeyError:
  1345.                 pass
  1346.             except:
  1347.                 None<EXCEPTION MATCH>KeyError
  1348.             
  1349.  
  1350.         None<EXCEPTION MATCH>KeyError
  1351.         if type in (CHRTYPE, BLKTYPE):
  1352.             if hasattr(os, 'major') and hasattr(os, 'minor'):
  1353.                 tarinfo.devmajor = os.major(statres.st_rdev)
  1354.                 tarinfo.devminor = os.minor(statres.st_rdev)
  1355.             
  1356.         
  1357.         return tarinfo
  1358.  
  1359.     
  1360.     def list(self, verbose = True):
  1361.         """Print a table of contents to sys.stdout. If `verbose' is False, only
  1362.            the names of the members are printed. If it is True, an `ls -l'-like
  1363.            output is produced.
  1364.         """
  1365.         self._check()
  1366.         for tarinfo in self:
  1367.             if verbose:
  1368.                 print filemode(tarinfo.mode),
  1369.                 if not tarinfo.uname:
  1370.                     pass
  1371.                 if not tarinfo.gname:
  1372.                     pass
  1373.                 print '%s/%s' % (tarinfo.uid, tarinfo.gid),
  1374.                 if tarinfo.ischr() or tarinfo.isblk():
  1375.                     print '%10s' % '%d,%d' % (tarinfo.devmajor, tarinfo.devminor),
  1376.                 else:
  1377.                     print '%10d' % tarinfo.size,
  1378.                 print '%d-%02d-%02d %02d:%02d:%02d' % time.localtime(tarinfo.mtime)[:6],
  1379.             
  1380.             print tarinfo.name,
  1381.             if verbose:
  1382.                 if tarinfo.issym():
  1383.                     print '->', tarinfo.linkname,
  1384.                 
  1385.                 if tarinfo.islnk():
  1386.                     print 'link to', tarinfo.linkname,
  1387.                 
  1388.             
  1389.             print 
  1390.         
  1391.  
  1392.     
  1393.     def add(self, name, arcname = None, recursive = True):
  1394.         """Add the file `name' to the archive. `name' may be any type of file
  1395.            (directory, fifo, symbolic link, etc.). If given, `arcname'
  1396.            specifies an alternative name for the file in the archive.
  1397.            Directories are added recursively by default. This can be avoided by
  1398.            setting `recursive' to False.
  1399.         """
  1400.         self._check('aw')
  1401.         if arcname is None:
  1402.             arcname = name
  1403.         
  1404.         if self.name is not None and os.path.abspath(name) == self.name:
  1405.             self._dbg(2, 'tarfile: Skipped %r' % name)
  1406.             return None
  1407.         
  1408.         if name == '.':
  1409.             if recursive:
  1410.                 if arcname == '.':
  1411.                     arcname = ''
  1412.                 
  1413.                 for f in os.listdir('.'):
  1414.                     self.add(f, os.path.join(arcname, f))
  1415.                 
  1416.             
  1417.             return None
  1418.         
  1419.         self._dbg(1, name)
  1420.         tarinfo = self.gettarinfo(name, arcname)
  1421.         if tarinfo is None:
  1422.             self._dbg(1, 'tarfile: Unsupported type %r' % name)
  1423.             return None
  1424.         
  1425.         if tarinfo.isreg():
  1426.             f = file(name, 'rb')
  1427.             self.addfile(tarinfo, f)
  1428.             f.close()
  1429.         elif tarinfo.isdir():
  1430.             self.addfile(tarinfo)
  1431.             if recursive:
  1432.                 for f in os.listdir(name):
  1433.                     self.add(os.path.join(name, f), os.path.join(arcname, f))
  1434.                 
  1435.             
  1436.         else:
  1437.             self.addfile(tarinfo)
  1438.  
  1439.     
  1440.     def addfile(self, tarinfo, fileobj = None):
  1441.         """Add the TarInfo object `tarinfo' to the archive. If `fileobj' is
  1442.            given, tarinfo.size bytes are read from it and added to the archive.
  1443.            You can create TarInfo objects using gettarinfo().
  1444.            On Windows platforms, `fileobj' should always be opened with mode
  1445.            'rb' to avoid irritation about the file size.
  1446.         """
  1447.         self._check('aw')
  1448.         tarinfo = copy.copy(tarinfo)
  1449.         buf = tarinfo.tobuf(self.posix)
  1450.         self.fileobj.write(buf)
  1451.         self.offset += len(buf)
  1452.         if fileobj is not None:
  1453.             copyfileobj(fileobj, self.fileobj, tarinfo.size)
  1454.             (blocks, remainder) = divmod(tarinfo.size, BLOCKSIZE)
  1455.             if remainder > 0:
  1456.                 self.fileobj.write(NUL * (BLOCKSIZE - remainder))
  1457.                 blocks += 1
  1458.             
  1459.             self.offset += blocks * BLOCKSIZE
  1460.         
  1461.         self.members.append(tarinfo)
  1462.  
  1463.     
  1464.     def extractall(self, path = '.', members = None):
  1465.         """Extract all members from the archive to the current working
  1466.            directory and set owner, modification time and permissions on
  1467.            directories afterwards. `path' specifies a different directory
  1468.            to extract to. `members' is optional and must be a subset of the
  1469.            list returned by getmembers().
  1470.         """
  1471.         directories = []
  1472.         if members is None:
  1473.             members = self
  1474.         
  1475.         for tarinfo in members:
  1476.             if tarinfo.isdir():
  1477.                 
  1478.                 try:
  1479.                     os.makedirs(os.path.join(path, tarinfo.name), 511)
  1480.                 except EnvironmentError:
  1481.                     pass
  1482.  
  1483.                 directories.append(tarinfo)
  1484.                 continue
  1485.             self.extract(tarinfo, path)
  1486.         
  1487.         directories.sort((lambda a, b: cmp(a.name, b.name)))
  1488.         directories.reverse()
  1489.         for tarinfo in directories:
  1490.             path = os.path.join(path, tarinfo.name)
  1491.             
  1492.             try:
  1493.                 self.chown(tarinfo, path)
  1494.                 self.utime(tarinfo, path)
  1495.                 self.chmod(tarinfo, path)
  1496.             continue
  1497.             except ExtractError:
  1498.                 e = None
  1499.                 if self.errorlevel > 1:
  1500.                     raise 
  1501.                 else:
  1502.                     self._dbg(1, 'tarfile: %s' % e)
  1503.                 self.errorlevel > 1
  1504.             
  1505.  
  1506.         
  1507.  
  1508.     
  1509.     def extract(self, member, path = ''):
  1510.         """Extract a member from the archive to the current working directory,
  1511.            using its full name. Its file information is extracted as accurately
  1512.            as possible. `member' may be a filename or a TarInfo object. You can
  1513.            specify a different directory using `path'.
  1514.         """
  1515.         self._check('r')
  1516.         if isinstance(member, TarInfo):
  1517.             tarinfo = member
  1518.         else:
  1519.             tarinfo = self.getmember(member)
  1520.         if tarinfo.islnk():
  1521.             tarinfo._link_target = os.path.join(path, tarinfo.linkname)
  1522.         
  1523.         
  1524.         try:
  1525.             self._extract_member(tarinfo, os.path.join(path, tarinfo.name))
  1526.         except EnvironmentError:
  1527.             e = None
  1528.             if self.errorlevel > 0:
  1529.                 raise 
  1530.             elif e.filename is None:
  1531.                 self._dbg(1, 'tarfile: %s' % e.strerror)
  1532.             else:
  1533.                 self._dbg(1, 'tarfile: %s %r' % (e.strerror, e.filename))
  1534.         except ExtractError:
  1535.             e = None
  1536.             if self.errorlevel > 1:
  1537.                 raise 
  1538.             else:
  1539.                 self._dbg(1, 'tarfile: %s' % e)
  1540.         except:
  1541.             self.errorlevel > 1
  1542.  
  1543.  
  1544.     
  1545.     def extractfile(self, member):
  1546.         """Extract a member from the archive as a file object. `member' may be
  1547.            a filename or a TarInfo object. If `member' is a regular file, a
  1548.            file-like object is returned. If `member' is a link, a file-like
  1549.            object is constructed from the link's target. If `member' is none of
  1550.            the above, None is returned.
  1551.            The file-like object is read-only and provides the following
  1552.            methods: read(), readline(), readlines(), seek() and tell()
  1553.         """
  1554.         self._check('r')
  1555.         if isinstance(member, TarInfo):
  1556.             tarinfo = member
  1557.         else:
  1558.             tarinfo = self.getmember(member)
  1559.         if tarinfo.isreg():
  1560.             return self.fileobject(self, tarinfo)
  1561.         elif tarinfo.type not in SUPPORTED_TYPES:
  1562.             return self.fileobject(self, tarinfo)
  1563.         elif tarinfo.islnk() or tarinfo.issym():
  1564.             if isinstance(self.fileobj, _Stream):
  1565.                 raise StreamError('cannot extract (sym)link as file object')
  1566.             else:
  1567.                 return self.extractfile(self._getmember(tarinfo.linkname, tarinfo))
  1568.         else:
  1569.             return None
  1570.  
  1571.     
  1572.     def _extract_member(self, tarinfo, targetpath):
  1573.         '''Extract the TarInfo object tarinfo to a physical
  1574.            file called targetpath.
  1575.         '''
  1576.         if targetpath[-1:] == '/':
  1577.             targetpath = targetpath[:-1]
  1578.         
  1579.         targetpath = os.path.normpath(targetpath)
  1580.         upperdirs = os.path.dirname(targetpath)
  1581.         if upperdirs and not os.path.exists(upperdirs):
  1582.             ti = TarInfo()
  1583.             ti.name = upperdirs
  1584.             ti.type = DIRTYPE
  1585.             ti.mode = 511
  1586.             ti.mtime = tarinfo.mtime
  1587.             ti.uid = tarinfo.uid
  1588.             ti.gid = tarinfo.gid
  1589.             ti.uname = tarinfo.uname
  1590.             ti.gname = tarinfo.gname
  1591.             
  1592.             try:
  1593.                 self._extract_member(ti, ti.name)
  1594.  
  1595.         
  1596.         if tarinfo.islnk() or tarinfo.issym():
  1597.             self._dbg(1, '%s -> %s' % (tarinfo.name, tarinfo.linkname))
  1598.         else:
  1599.             self._dbg(1, tarinfo.name)
  1600.         if tarinfo.isreg():
  1601.             self.makefile(tarinfo, targetpath)
  1602.         elif tarinfo.isdir():
  1603.             self.makedir(tarinfo, targetpath)
  1604.         elif tarinfo.isfifo():
  1605.             self.makefifo(tarinfo, targetpath)
  1606.         elif tarinfo.ischr() or tarinfo.isblk():
  1607.             self.makedev(tarinfo, targetpath)
  1608.         elif tarinfo.islnk() or tarinfo.issym():
  1609.             self.makelink(tarinfo, targetpath)
  1610.         elif tarinfo.type not in SUPPORTED_TYPES:
  1611.             self.makeunknown(tarinfo, targetpath)
  1612.         else:
  1613.             self.makefile(tarinfo, targetpath)
  1614.         self.chown(tarinfo, targetpath)
  1615.         if not tarinfo.issym():
  1616.             self.chmod(tarinfo, targetpath)
  1617.             self.utime(tarinfo, targetpath)
  1618.         
  1619.  
  1620.     
  1621.     def makedir(self, tarinfo, targetpath):
  1622.         '''Make a directory called targetpath.
  1623.         '''
  1624.         
  1625.         try:
  1626.             os.mkdir(targetpath)
  1627.         except EnvironmentError:
  1628.             e = None
  1629.             if e.errno != errno.EEXIST:
  1630.                 raise 
  1631.             
  1632.         except:
  1633.             e.errno != errno.EEXIST
  1634.  
  1635.  
  1636.     
  1637.     def makefile(self, tarinfo, targetpath):
  1638.         '''Make a file called targetpath.
  1639.         '''
  1640.         source = self.extractfile(tarinfo)
  1641.         target = file(targetpath, 'wb')
  1642.         copyfileobj(source, target)
  1643.         source.close()
  1644.         target.close()
  1645.  
  1646.     
  1647.     def makeunknown(self, tarinfo, targetpath):
  1648.         '''Make a file from a TarInfo object with an unknown type
  1649.            at targetpath.
  1650.         '''
  1651.         self.makefile(tarinfo, targetpath)
  1652.         self._dbg(1, 'tarfile: Unknown file type %r, extracted as regular file.' % tarinfo.type)
  1653.  
  1654.     
  1655.     def makefifo(self, tarinfo, targetpath):
  1656.         '''Make a fifo called targetpath.
  1657.         '''
  1658.         if hasattr(os, 'mkfifo'):
  1659.             os.mkfifo(targetpath)
  1660.         else:
  1661.             raise ExtractError('fifo not supported by system')
  1662.  
  1663.     
  1664.     def makedev(self, tarinfo, targetpath):
  1665.         '''Make a character or block device called targetpath.
  1666.         '''
  1667.         if not hasattr(os, 'mknod') or not hasattr(os, 'makedev'):
  1668.             raise ExtractError('special devices not supported by system')
  1669.         
  1670.         mode = tarinfo.mode
  1671.         if tarinfo.isblk():
  1672.             mode |= stat.S_IFBLK
  1673.         else:
  1674.             mode |= stat.S_IFCHR
  1675.         os.mknod(targetpath, mode, os.makedev(tarinfo.devmajor, tarinfo.devminor))
  1676.  
  1677.     
  1678.     def makelink(self, tarinfo, targetpath):
  1679.         '''Make a (symbolic) link called targetpath. If it cannot be created
  1680.           (platform limitation), we try to make a copy of the referenced file
  1681.           instead of a link.
  1682.         '''
  1683.         linkpath = tarinfo.linkname
  1684.         
  1685.         try:
  1686.             if tarinfo.issym():
  1687.                 os.symlink(linkpath, targetpath)
  1688.             else:
  1689.                 os.link(tarinfo._link_target, targetpath)
  1690.         except AttributeError:
  1691.             if tarinfo.issym():
  1692.                 linkpath = os.path.join(os.path.dirname(tarinfo.name), linkpath)
  1693.                 linkpath = normpath(linkpath)
  1694.             
  1695.             
  1696.             try:
  1697.                 self._extract_member(self.getmember(linkpath), targetpath)
  1698.             except (EnvironmentError, KeyError):
  1699.                 e = None
  1700.                 linkpath = os.path.normpath(linkpath)
  1701.                 
  1702.                 try:
  1703.                     shutil.copy2(linkpath, targetpath)
  1704.                 except EnvironmentError:
  1705.                     e = None
  1706.                     raise IOError('link could not be created')
  1707.                 except:
  1708.                     None<EXCEPTION MATCH>EnvironmentError
  1709.                 
  1710.  
  1711.                 None<EXCEPTION MATCH>EnvironmentError
  1712.             
  1713.  
  1714.             None<EXCEPTION MATCH>(EnvironmentError, KeyError)
  1715.  
  1716.  
  1717.     
  1718.     def chown(self, tarinfo, targetpath):
  1719.         '''Set owner of targetpath according to tarinfo.
  1720.         '''
  1721.         if pwd and hasattr(os, 'geteuid') and os.geteuid() == 0:
  1722.             
  1723.             try:
  1724.                 g = grp.getgrnam(tarinfo.gname)[2]
  1725.             except KeyError:
  1726.                 
  1727.                 try:
  1728.                     g = grp.getgrgid(tarinfo.gid)[2]
  1729.                 except KeyError:
  1730.                     g = os.getgid()
  1731.                 except:
  1732.                     None<EXCEPTION MATCH>KeyError
  1733.                 
  1734.  
  1735.                 None<EXCEPTION MATCH>KeyError
  1736.  
  1737.             
  1738.             try:
  1739.                 u = pwd.getpwnam(tarinfo.uname)[2]
  1740.             except KeyError:
  1741.                 
  1742.                 try:
  1743.                     u = pwd.getpwuid(tarinfo.uid)[2]
  1744.                 except KeyError:
  1745.                     u = os.getuid()
  1746.                 except:
  1747.                     None<EXCEPTION MATCH>KeyError
  1748.                 
  1749.  
  1750.                 None<EXCEPTION MATCH>KeyError
  1751.  
  1752.             
  1753.             try:
  1754.                 if tarinfo.issym() and hasattr(os, 'lchown'):
  1755.                     os.lchown(targetpath, u, g)
  1756.                 elif sys.platform != 'os2emx':
  1757.                     os.chown(targetpath, u, g)
  1758.             except EnvironmentError:
  1759.                 e = None
  1760.                 raise ExtractError('could not change owner')
  1761.             except:
  1762.                 None<EXCEPTION MATCH>EnvironmentError
  1763.             
  1764.  
  1765.         None<EXCEPTION MATCH>EnvironmentError
  1766.  
  1767.     
  1768.     def chmod(self, tarinfo, targetpath):
  1769.         '''Set file permissions of targetpath according to tarinfo.
  1770.         '''
  1771.         if hasattr(os, 'chmod'):
  1772.             
  1773.             try:
  1774.                 os.chmod(targetpath, tarinfo.mode)
  1775.             except EnvironmentError:
  1776.                 e = None
  1777.                 raise ExtractError('could not change mode')
  1778.             except:
  1779.                 None<EXCEPTION MATCH>EnvironmentError
  1780.             
  1781.  
  1782.         None<EXCEPTION MATCH>EnvironmentError
  1783.  
  1784.     
  1785.     def utime(self, tarinfo, targetpath):
  1786.         '''Set modification time of targetpath according to tarinfo.
  1787.         '''
  1788.         if not hasattr(os, 'utime'):
  1789.             return None
  1790.         
  1791.         if sys.platform == 'win32' and tarinfo.isdir():
  1792.             return None
  1793.         
  1794.         
  1795.         try:
  1796.             os.utime(targetpath, (tarinfo.mtime, tarinfo.mtime))
  1797.         except EnvironmentError:
  1798.             e = None
  1799.             raise ExtractError('could not change modification time')
  1800.  
  1801.  
  1802.     
  1803.     def next(self):
  1804.         '''Return the next member of the archive as a TarInfo object, when
  1805.            TarFile is opened for reading. Return None if there is no more
  1806.            available.
  1807.         '''
  1808.         self._check('ra')
  1809.         if self.firstmember is not None:
  1810.             m = self.firstmember
  1811.             self.firstmember = None
  1812.             return m
  1813.         
  1814.         self.fileobj.seek(self.offset)
  1815.         while True:
  1816.             buf = self.fileobj.read(BLOCKSIZE)
  1817.             if not buf:
  1818.                 return None
  1819.             
  1820.             
  1821.             try:
  1822.                 tarinfo = TarInfo.frombuf(buf)
  1823.                 tarinfo.offset = self.offset
  1824.                 self.offset += BLOCKSIZE
  1825.                 tarinfo = self.proc_member(tarinfo)
  1826.             except ValueError:
  1827.                 e = None
  1828.                 if self.ignore_zeros:
  1829.                     self._dbg(2, '0x%X: empty or invalid block: %s' % (self.offset, e))
  1830.                     self.offset += BLOCKSIZE
  1831.                     continue
  1832.                 elif self.offset == 0:
  1833.                     raise ReadError('empty, unreadable or compressed file: %s' % e)
  1834.                 
  1835.                 return None
  1836.  
  1837.             break
  1838.         if tarinfo.isreg() and tarinfo.name.endswith('/'):
  1839.             tarinfo.type = DIRTYPE
  1840.         
  1841.         if tarinfo.isdir():
  1842.             tarinfo.name += '/'
  1843.         
  1844.         self.members.append(tarinfo)
  1845.         return tarinfo
  1846.  
  1847.     
  1848.     def proc_member(self, tarinfo):
  1849.         '''Choose the right processing method for tarinfo depending
  1850.            on its type and call it.
  1851.         '''
  1852.         if tarinfo.type in (GNUTYPE_LONGNAME, GNUTYPE_LONGLINK):
  1853.             return self.proc_gnulong(tarinfo)
  1854.         elif tarinfo.type == GNUTYPE_SPARSE:
  1855.             return self.proc_sparse(tarinfo)
  1856.         else:
  1857.             return self.proc_builtin(tarinfo)
  1858.  
  1859.     
  1860.     def proc_builtin(self, tarinfo):
  1861.         '''Process a builtin type member or an unknown member
  1862.            which will be treated as a regular file.
  1863.         '''
  1864.         tarinfo.offset_data = self.offset
  1865.         if tarinfo.isreg() or tarinfo.type not in SUPPORTED_TYPES:
  1866.             self.offset += self._block(tarinfo.size)
  1867.         
  1868.         return tarinfo
  1869.  
  1870.     
  1871.     def proc_gnulong(self, tarinfo):
  1872.         '''Process the blocks that hold a GNU longname
  1873.            or longlink member.
  1874.         '''
  1875.         buf = ''
  1876.         count = tarinfo.size
  1877.         while count > 0:
  1878.             block = self.fileobj.read(BLOCKSIZE)
  1879.             buf += block
  1880.             self.offset += BLOCKSIZE
  1881.             count -= BLOCKSIZE
  1882.             continue
  1883.             self
  1884.         b = self.fileobj.read(BLOCKSIZE)
  1885.         t = TarInfo.frombuf(b)
  1886.         t.offset = self.offset
  1887.         self.offset += BLOCKSIZE
  1888.         next = self.proc_member(t)
  1889.         next.offset = tarinfo.offset
  1890.         if tarinfo.type == GNUTYPE_LONGNAME:
  1891.             next.name = buf.rstrip(NUL)
  1892.         elif tarinfo.type == GNUTYPE_LONGLINK:
  1893.             next.linkname = buf.rstrip(NUL)
  1894.         
  1895.         return next
  1896.  
  1897.     
  1898.     def proc_sparse(self, tarinfo):
  1899.         '''Process a GNU sparse header plus extra headers.
  1900.         '''
  1901.         buf = tarinfo.buf
  1902.         sp = _ringbuffer()
  1903.         pos = 386
  1904.         lastpos = 0x0L
  1905.         realpos = 0x0L
  1906.         for i in xrange(4):
  1907.             
  1908.             try:
  1909.                 offset = nti(buf[pos:pos + 12])
  1910.                 numbytes = nti(buf[pos + 12:pos + 24])
  1911.             except ValueError:
  1912.                 break
  1913.  
  1914.             if offset > lastpos:
  1915.                 sp.append(_hole(lastpos, offset - lastpos))
  1916.             
  1917.             sp.append(_data(offset, numbytes, realpos))
  1918.             realpos += numbytes
  1919.             lastpos = offset + numbytes
  1920.             pos += 24
  1921.         
  1922.         isextended = ord(buf[482])
  1923.         origsize = nti(buf[483:495])
  1924.         while isextended == 1:
  1925.             buf = self.fileobj.read(BLOCKSIZE)
  1926.             self.offset += BLOCKSIZE
  1927.             pos = 0
  1928.             for i in xrange(21):
  1929.                 
  1930.                 try:
  1931.                     offset = nti(buf[pos:pos + 12])
  1932.                     numbytes = nti(buf[pos + 12:pos + 24])
  1933.                 except ValueError:
  1934.                     self
  1935.                     self
  1936.                     break
  1937.                 except:
  1938.                     self
  1939.  
  1940.                 if offset > lastpos:
  1941.                     sp.append(_hole(lastpos, offset - lastpos))
  1942.                 
  1943.                 sp.append(_data(offset, numbytes, realpos))
  1944.                 realpos += numbytes
  1945.                 lastpos = offset + numbytes
  1946.                 pos += 24
  1947.             
  1948.             isextended = ord(buf[504])
  1949.         if lastpos < origsize:
  1950.             sp.append(_hole(lastpos, origsize - lastpos))
  1951.         
  1952.         tarinfo.sparse = sp
  1953.         tarinfo.offset_data = self.offset
  1954.         self.offset += self._block(tarinfo.size)
  1955.         tarinfo.size = origsize
  1956.         return tarinfo
  1957.  
  1958.     
  1959.     def _block(self, count):
  1960.         '''Round up a byte count by BLOCKSIZE and return it,
  1961.            e.g. _block(834) => 1024.
  1962.         '''
  1963.         (blocks, remainder) = divmod(count, BLOCKSIZE)
  1964.         if remainder:
  1965.             blocks += 1
  1966.         
  1967.         return blocks * BLOCKSIZE
  1968.  
  1969.     
  1970.     def _getmember(self, name, tarinfo = None):
  1971.         '''Find an archive member by name from bottom to top.
  1972.            If tarinfo is given, it is used as the starting point.
  1973.         '''
  1974.         members = self.getmembers()
  1975.         if tarinfo is None:
  1976.             end = len(members)
  1977.         else:
  1978.             end = members.index(tarinfo)
  1979.         for i in xrange(end - 1, -1, -1):
  1980.             if name == members[i].name:
  1981.                 return members[i]
  1982.                 continue
  1983.         
  1984.  
  1985.     
  1986.     def _load(self):
  1987.         '''Read through the entire archive file and look for readable
  1988.            members.
  1989.         '''
  1990.         while True:
  1991.             tarinfo = self.next()
  1992.             if tarinfo is None:
  1993.                 break
  1994.                 continue
  1995.         self._loaded = True
  1996.  
  1997.     
  1998.     def _check(self, mode = None):
  1999.         """Check if TarFile is still open, and if the operation's mode
  2000.            corresponds to TarFile's mode.
  2001.         """
  2002.         if self.closed:
  2003.             raise IOError('%s is closed' % self.__class__.__name__)
  2004.         
  2005.         if mode is not None and self._mode not in mode:
  2006.             raise IOError('bad operation for mode %r' % self._mode)
  2007.         
  2008.  
  2009.     
  2010.     def __iter__(self):
  2011.         '''Provide an iterator object.
  2012.         '''
  2013.         if self._loaded:
  2014.             return iter(self.members)
  2015.         else:
  2016.             return TarIter(self)
  2017.  
  2018.     
  2019.     def _dbg(self, level, msg):
  2020.         '''Write debugging output to sys.stderr.
  2021.         '''
  2022.         if level <= self.debug:
  2023.             print >>sys.stderr, msg
  2024.         
  2025.  
  2026.  
  2027.  
  2028. class TarIter:
  2029.     '''Iterator Class.
  2030.  
  2031.        for tarinfo in TarFile(...):
  2032.            suite...
  2033.     '''
  2034.     
  2035.     def __init__(self, tarfile):
  2036.         '''Construct a TarIter object.
  2037.         '''
  2038.         self.tarfile = tarfile
  2039.         self.index = 0
  2040.  
  2041.     
  2042.     def __iter__(self):
  2043.         '''Return iterator object.
  2044.         '''
  2045.         return self
  2046.  
  2047.     
  2048.     def next(self):
  2049.         """Return the next item using TarFile's next() method.
  2050.            When all members have been read, set TarFile as _loaded.
  2051.         """
  2052.         if not self.tarfile._loaded:
  2053.             tarinfo = self.tarfile.next()
  2054.             if not tarinfo:
  2055.                 self.tarfile._loaded = True
  2056.                 raise StopIteration
  2057.             
  2058.         else:
  2059.             
  2060.             try:
  2061.                 tarinfo = self.tarfile.members[self.index]
  2062.             except IndexError:
  2063.                 raise StopIteration
  2064.  
  2065.         self.index += 1
  2066.         return tarinfo
  2067.  
  2068.  
  2069.  
  2070. class _section:
  2071.     '''Base class for _data and _hole.
  2072.     '''
  2073.     
  2074.     def __init__(self, offset, size):
  2075.         self.offset = offset
  2076.         self.size = size
  2077.  
  2078.     
  2079.     def __contains__(self, offset):
  2080.         return None if offset <= offset else offset < self.offset + self.size
  2081.  
  2082.  
  2083.  
  2084. class _data(_section):
  2085.     '''Represent a data section in a sparse file.
  2086.     '''
  2087.     
  2088.     def __init__(self, offset, size, realpos):
  2089.         _section.__init__(self, offset, size)
  2090.         self.realpos = realpos
  2091.  
  2092.  
  2093.  
  2094. class _hole(_section):
  2095.     '''Represent a hole section in a sparse file.
  2096.     '''
  2097.     pass
  2098.  
  2099.  
  2100. class _ringbuffer(list):
  2101.     '''Ringbuffer class which increases performance
  2102.        over a regular list.
  2103.     '''
  2104.     
  2105.     def __init__(self):
  2106.         self.idx = 0
  2107.  
  2108.     
  2109.     def find(self, offset):
  2110.         idx = self.idx
  2111.         while True:
  2112.             item = self[idx]
  2113.             if offset in item:
  2114.                 break
  2115.             
  2116.             idx += 1
  2117.             if idx == len(self):
  2118.                 idx = 0
  2119.             
  2120.             if idx == self.idx:
  2121.                 return None
  2122.                 continue
  2123.         self.idx = idx
  2124.         return item
  2125.  
  2126.  
  2127. TAR_PLAIN = 0
  2128. TAR_GZIPPED = 8
  2129.  
  2130. class TarFileCompat:
  2131.     """TarFile class compatible with standard module zipfile's
  2132.        ZipFile class.
  2133.     """
  2134.     
  2135.     def __init__(self, file, mode = 'r', compression = TAR_PLAIN):
  2136.         if compression == TAR_PLAIN:
  2137.             self.tarfile = TarFile.taropen(file, mode)
  2138.         elif compression == TAR_GZIPPED:
  2139.             self.tarfile = TarFile.gzopen(file, mode)
  2140.         else:
  2141.             raise ValueError('unknown compression constant')
  2142.         if mode[0:1] == 'r':
  2143.             members = self.tarfile.getmembers()
  2144.             for m in members:
  2145.                 m.filename = m.name
  2146.                 m.file_size = m.size
  2147.                 m.date_time = time.gmtime(m.mtime)[:6]
  2148.             
  2149.         
  2150.  
  2151.     
  2152.     def namelist(self):
  2153.         return map((lambda m: m.name), self.infolist())
  2154.  
  2155.     
  2156.     def infolist(self):
  2157.         return filter((lambda m: m.type in REGULAR_TYPES), self.tarfile.getmembers())
  2158.  
  2159.     
  2160.     def printdir(self):
  2161.         self.tarfile.list()
  2162.  
  2163.     
  2164.     def testzip(self):
  2165.         pass
  2166.  
  2167.     
  2168.     def getinfo(self, name):
  2169.         return self.tarfile.getmember(name)
  2170.  
  2171.     
  2172.     def read(self, name):
  2173.         return self.tarfile.extractfile(self.tarfile.getmember(name)).read()
  2174.  
  2175.     
  2176.     def write(self, filename, arcname = None, compress_type = None):
  2177.         self.tarfile.add(filename, arcname)
  2178.  
  2179.     
  2180.     def writestr(self, zinfo, bytes):
  2181.         
  2182.         try:
  2183.             StringIO = StringIO
  2184.             import cStringIO
  2185.         except ImportError:
  2186.             StringIO = StringIO
  2187.             import StringIO
  2188.  
  2189.         import calendar
  2190.         zinfo.name = zinfo.filename
  2191.         zinfo.size = zinfo.file_size
  2192.         zinfo.mtime = calendar.timegm(zinfo.date_time)
  2193.         self.tarfile.addfile(zinfo, StringIO(bytes))
  2194.  
  2195.     
  2196.     def close(self):
  2197.         self.tarfile.close()
  2198.  
  2199.  
  2200.  
  2201. def is_tarfile(name):
  2202.     '''Return True if name points to a tar archive that we
  2203.        are able to handle, else return False.
  2204.     '''
  2205.     
  2206.     try:
  2207.         t = open(name)
  2208.         t.close()
  2209.         return True
  2210.     except TarError:
  2211.         return False
  2212.  
  2213.  
  2214. open = TarFile.open
  2215.